package com.ytjj.qmyx.users.controller;

import com.alibaba.fastjson.JSONObject;
import com.ytjj.common.api.CommonResult;
import com.ytjj.common.api.ResultCode;
import com.ytjj.common.constants.SysConfigConstants;
import com.ytjj.common.constants.TokenConstants;
import com.ytjj.common.controller.BaseController;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.model.UsersResponse;
import com.ytjj.common.service.WxUtils;
import com.ytjj.common.utils.*;
import com.ytjj.qmyx.mall.client.MallClient;
import com.ytjj.qmyx.mall.model.PayConfigDto;
import com.ytjj.qmyx.users.constants.CompanyConstant;
import com.ytjj.qmyx.users.constants.NewWxConstants;
import com.ytjj.qmyx.users.constants.WxConstants;
import com.ytjj.qmyx.users.model.SmsToolEnterPhone;
import com.ytjj.qmyx.users.model.dto.WeixinPhoneDecryptInfo;
import com.ytjj.qmyx.users.model.request.AppLoginRequest;
import com.ytjj.qmyx.users.model.request.GetH5WxJsSdkRequest;
import com.ytjj.qmyx.users.model.request.LoginRequest;
import com.ytjj.qmyx.users.model.request.RegisterRequest;
import com.ytjj.qmyx.users.service.LoginService;
import com.ytjj.qmyx.users.service.RedisService;
import com.ytjj.qmyx.users.service.SmsToolEnterPhoneService;
import com.ytjj.qmyx.users.service.UsersService;
import com.ytjj.qmyx.users.utils.AESForWeixinGetPhoneNumber;
import com.ytjj.qmyx.users.utils.GetTokenUtil;
import com.ytjj.qmyx.users.utils.IPUtil;
import com.ytjj.qmyx.users.utils.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @Description APP登录接口
 *
 * @Version 1.0
 * 
 */
@Slf4j
@RestController
@RequestMapping("/login")
@Validated
@RefreshScope
public class LoginController extends BaseController {

    private final LoginService loginService;

    private final RedisService redisService;

    private final MallClient mallClient;

    private final UsersService usersService;
    @Value("${encodeRules:ytjj2021}")
    private String encodeRules;
    /**
     * 登录黑名单
     */
    @Value("${blacklist.tel:18811193193,15754211002,13052614691,18873058010}")
    private String blackListTel;
    @Autowired
    private SmsToolEnterPhoneService smsToolEnterPhoneService;

    public LoginController(LoginService loginService, RedisService redisService, MallClient mallClient, UsersService usersService) {
        this.loginService = loginService;
        this.redisService = redisService;
        this.mallClient = mallClient;
        this.usersService = usersService;
    }

    /**
     * h5登陆
     *
     * @return
     */
    @GetMapping("/h5Login")
    public CommonResult h5Login(@RequestParam(value = "channel", required = false) String channel,
                                @RequestParam(value = "sourcePlatform", required = false) String sourcePlatform,
                                @RequestParam(value="serialNumber", required = false) String serialNumber) {
        log.debug("===phone:{}===", serialNumber);
        String token = TokenUtil.getToken();
        channel = TokenUtil.getRequest().getHeader("channel");
        if (!StringUtils.isEmpty(serialNumber)) {
            //短链进入 并且携带了phone参数
            token = resolutionSmsToolsData(serialNumber);
            log.debug("===back token==={}", token);
            String tel = resolutionSmsToolsPhone(serialNumber);
            if (!StringUtils.isEmpty(token)) {
                UsersResponse usersResponse = this.getH5CurrentUser(sourcePlatform, token);
                log.debug("===短链进入用户开始注册===");
                Integer userId = usersService.doNewUserRegister(usersResponse.getNickname(), tel, token, channel,
                        usersResponse.getMoney(), usersResponse.getScore(),
                        usersResponse.getTotalMoney(), usersResponse.getTotalScore());
                log.debug("===短链进入用户完成注册==={}", userId);
                return CommonResult.success(usersResponse);
            }
        }
        if (null == token) {
            return CommonResult.success(loginService.h5Login(this.getSource(), channel,sourcePlatform, token));
        } else {
            UsersResponse usersResponse = this.getH5CurrentUser(sourcePlatform);
            if (null == usersResponse) {
                return CommonResult.success(loginService.h5Login(this.getSource(), channel,sourcePlatform, token));
            }
            return CommonResult.success(usersResponse);
        }
    }

    /**
     * 绑定推啊id
     *
     * @return
     */
    @GetMapping("/bindAoId")
    public CommonResult h5Login(@RequestParam(value = "token") String token,
                                @RequestParam(value = "aoId") String aoId) {
        if (StringUtils.isBlank(token) || StringUtils.isBlank(aoId)) {
            throw new ApiException("token 和 aoId 不能为空");
        }
        UsersResponse usersResponse = this.getH5CurrentUser(token);
        if (null == usersResponse) {
            throw new ApiException("根据token查询用户失败！");
        }
        if (StringUtils.isBlank(usersResponse.getAoId())) {
            usersResponse.setAoId(aoId);
        }
        redisService.set(token,JSONObject.toJSONString(usersResponse));
        redisService.expire(token, TokenConstants.EXPIRE_SECONDS);
        return CommonResult.success(usersResponse);
    }

    /**
     * 解析短链的加密phone
     * @param phoneCode 密文手机号
     * @return  解密出来的手机号
     */
    private String resolutionSmsToolsPhone(String phoneCode) {
        try {
            phoneCode = phoneCode.replaceAll("%2B", "+");
            phoneCode = phoneCode.replaceAll("%3D", "=");
            phoneCode = phoneCode.replaceAll("%2F", "/");
            String phoneDeCode = Aes128CBCUtil.decrypt(phoneCode, "eCcgc+=F'=M)$+'+", "g&_&J{~mK~e#h_Y2");
            log.debug("===解析短链手机号==={}", phoneDeCode);
            return phoneDeCode;
        } catch (Exception e) {
            log.error("===解析短链手机号异常==={}", e);
        }
        return null;
    }

    /**
     * 根据手机号来保存用户进入记录
     * @param phoneCode
     * @return token
     */
    public String resolutionSmsToolsData(String phoneCode) {
        try {
            String phoneDeCode = resolutionSmsToolsPhone(phoneCode);
            log.debug("===解析短链手机号==={}", phoneDeCode);
            SmsToolEnterPhone enterPhoneBean = smsToolEnterPhoneService.getByPhone(phoneDeCode);
            if (null == enterPhoneBean) {
                enterPhoneBean = new SmsToolEnterPhone();
                enterPhoneBean.setPhone(phoneDeCode);
                enterPhoneBean.setToken(GetTokenUtil.getToken());
                smsToolEnterPhoneService.save(enterPhoneBean);
                return enterPhoneBean.getToken();
            }
            return StringUtils.isEmpty(enterPhoneBean.getToken()) ? null : enterPhoneBean.getToken();
        } catch (Exception e) {
            log.error("===解析短链手机号异常==={}", e);
        }
        return null;
    }

    /**
     * 获取h5微信js授权sdk
     * @param request
     * @return
     */
    @PostMapping("getH5WxJsSdk")
    public CommonResult getH5WxJsSdk(@RequestBody GetH5WxJsSdkRequest request) {
        PayConfigDto payConfigDto = mallClient.getPayConfigByCompany(CompanyConstant.NEW_PLATFORM);
        log.info("getH5WxJsSdk 响应：json:{}", JSONObject.toJSONString(payConfigDto));
        return CommonResult.success(WxUtils.getJsSdk(payConfigDto.getTicket(), payConfigDto.getPayPageUri(),payConfigDto.getAppid()));
    }

    /**
     * h5 获取用户信息
     *
     * @return
     */
    @GetMapping("/getH5WxUid")
    public CommonResult getH5WxUid(@RequestParam("code") String code) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", NewWxConstants.WX_MWEB_APPID);
        param.put("secret", NewWxConstants.WX_MWEB_SECRET);
        param.put("code", code);
        param.put("grant_type", NewWxConstants.WX_APPLET_LOGIN_GRANT_TYPE);
        log.info("getH5WxUid 登陆响应：json:{}", JSONObject.toJSONString(param));
        // 发送请求
        String wxResult = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/oauth2/access_token", param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.info("getH5WxUid,登陆响应：json:{}", JSONObject.toJSONString(jsonObject));
        return CommonResult.success(jsonObject);
    }

    /**
     * 第二个公众号
     * @param code
     * @return
     */
    @GetMapping("/getH5WxUid2")
    public CommonResult getH5WxUid2(@RequestParam("code") String code) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", NewWxConstants.WX_MWEB_APPID2);
        param.put("secret", NewWxConstants.WX_MWEB_SECRET2);
        param.put("code", code);
        param.put("grant_type", NewWxConstants.WX_APPLET_LOGIN_GRANT_TYPE);
        log.info("getH5WxUid 登陆响应：json:{}", JSONObject.toJSONString(param));
        // 发送请求
        String wxResult = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/oauth2/access_token", param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.info("getH5WxUid2,登陆响应：json:{}", JSONObject.toJSONString(jsonObject));
        return CommonResult.success(jsonObject);
    }


    /**
     * 小程序获取用户Uid
     *
     * @return
     */
    @GetMapping("/getWxUid")
    public CommonResult getWxUid(@RequestParam("code") String code) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", WxConstants.WX_APPLET_APPID_ZXLP);
        param.put("secret", WxConstants.WX_APPLET_SECRET_ZXLP);
        param.put("js_code", code);
        param.put("grant_type", WxConstants.WX_APPLET_LOGIN_GRANT_TYPE);
        // 发送请求
        String wxResult = HttpClientUtil.doGet(WxConstants.WX_APPLET_LOGIN_URL, param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.info("登陆响应：json:{}", JSONObject.toJSONString(jsonObject));
        return CommonResult.success(jsonObject);
    }

    /**
     *  根据unionId登录
     * @param registerRequest
     * @return
     */
    @PostMapping("/wxUnionIdLogin")
    public CommonResult<com.ytjj.qmyx.users.model.response.UsersResponse> wxUnionIdLogin(@RequestBody RegisterRequest registerRequest){
        registerRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        registerRequest.setSource(getSource());
        log.info("=======channel,{}",TokenUtil.getRequest().getHeader("channel"));
        registerRequest.setChannel(TokenUtil.getRequest().getHeader("channel"));
        log.info("-------channel,{}",registerRequest.getChannel());
        log.info("===wxUnionIdLogin===WxOpenid{},unionid={}", registerRequest.getOpenid(),registerRequest.getUnionid());

        return loginService.wxUnionIdLogin(registerRequest);
    }

    /**
     * APP获取用户Token
     *
     * @return
     */
    @GetMapping("/getAppWxToken")
    public CommonResult getAppWxToken(@RequestParam("code") String code) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", WxConstants.WX_APP_ID);
        param.put("secret", WxConstants.WX_APP_SECRET);
        param.put("code", code);
        param.put("grant_type", WxConstants.WX_APPLET_LOGIN_GRANT_TYPE);
        // 发送请求
        String wxResult = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/oauth2/access_token", param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.debug("登陆响应：json:{}", JSONObject.toJSONString(jsonObject));
        try {
            UsersResponse usersResponse = this.getCurrentUser();
            if (null != usersResponse) {
                log.info("===openId==={}", jsonObject.get("openid").toString());
                usersService.updateUserWxOpenId(usersResponse.getId(), jsonObject.get("openid").toString());
            }
        } catch (Exception e) {
            log.error("===异常==={}", e);
        }

        return CommonResult.success(jsonObject);
    }



    /**
     * APP获取用户信息
     * @param accessToken
     * @param openid
     * @return
     */
    @GetMapping("/getAppWxUserinfo")
    public CommonResult getAppWxUserinfo(@RequestParam("accessToken") String accessToken,
                                         @RequestParam("openid") String openid){
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("access_token",accessToken);
        param.put("openid", openid);
        param.put("lang", "zh_CN");
        // 发送请求
        String wxResult = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/userinfo", param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.debug("登陆响应：json:{}", JSONObject.toJSONString(jsonObject));
        return CommonResult.success(jsonObject);
    }


    @GetMapping("/saveOpenId")
    public void saveOpenId(@RequestParam("userId") Integer userId,
                           @RequestParam("openid") String openid){
        loginService.saveOpenId(userId,openid);
    }

    /**
     * app 登陆
     *
     * @param loginRequest
     * @return
     */
    @PostMapping("/login")
    public CommonResult login(@RequestBody LoginRequest loginRequest) {
        loginRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        return CommonResult.success(loginService.appLogin(loginRequest));
    }

    @PostMapping("/appLoginIos")
    public CommonResult appLoginIos(@RequestBody LoginRequest loginRequest) {
        loginRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        return CommonResult.success(loginService.appLoginByIos(loginRequest));
    }

    /**
     * 小程序 登陆
     *
     * @param loginRequest
     * @return
     */
    @PostMapping("/wxLogin")
    public CommonResult wxLogin(@RequestBody LoginRequest loginRequest) {
        loginRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        return CommonResult.success(loginService.wxLogin(loginRequest));
    }

    /**
     * app 注册登陆
     *
     * @param loginRequest
     * @return
     */
    @PostMapping("/register")
    public CommonResult appRegister(@RequestBody LoginRequest loginRequest) {
        loginRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        loginRequest.setChannel(TokenUtil.getRequest().getHeader("channel"));
        return CommonResult.success(loginService.appRegister(loginRequest));
    }

    /**
     * 根据电话 + 验证码注册用户 -> 手机号登录
     *
     * @return
     */
    @PostMapping("/phoneRegister")
    public CommonResult register(@RequestBody RegisterRequest registerRequest) {
        String tel = registerRequest.getTelephone();
        if (StringUtils.isNotEmpty(tel) && StringUtils.isNotEmpty(blackListTel)) {
            List<String> blackTelList = Arrays.asList(blackListTel.split(","));
            if (!CollectionUtils.isEmpty(blackTelList)) {
                if (blackTelList.contains(tel)) {
                    return CommonResult.failed("登录失败！");
                }
            }
        }
        registerRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        registerRequest.setSource(getSource());
        registerRequest.setChannel(TokenUtil.getRequest().getHeader("channel"));
        return loginService.register(registerRequest);
    }

    /**
     * 极光token 登录
     *
     * @param registerRequest
     * @return
     */
    @PostMapping("/tokenLogin")
    public CommonResult tokenLogin(@RequestBody RegisterRequest registerRequest){
        registerRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        registerRequest.setChannel(TokenUtil.getRequest().getHeader("channel"));
        registerRequest.setSource(getSource());
        try {
            String phone = RSADecrypt.decrypt(registerRequest.getLoginToken());
            if (StringUtils.isNotEmpty(phone) && StringUtils.isNotEmpty(blackListTel)) {
                List<String> blackTelList = Arrays.asList(blackListTel.split(","));
                if (!CollectionUtils.isEmpty(blackTelList)) {
                    if (blackTelList.contains(phone)) {
                        return CommonResult.failed("登录失败！");
                    }
                }
            }
            registerRequest.setTelephone(phone);
        } catch (Exception e) {
            log.error("一键登录失败：{}",getExceptionToString(e));
            return CommonResult.failed("登录失败，请关掉WIFI重试！");
        }
        return loginService.tokenLogin(registerRequest);
    }

    /**
     * 微信手机号登录
     * @param registerRequest
     * @return
     */
    @PostMapping("/wxPhoneLogin")
    public CommonResult wxPhoneLogin(@RequestBody RegisterRequest registerRequest){
        registerRequest.setIp(IPUtil.getIpAddress(TokenUtil.getRequest()));
        registerRequest.setSource(getSource());
        registerRequest.setChannel(TokenUtil.getRequest().getHeader("channel"));
        try {
            AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(registerRequest.getEncryptDataB64(),registerRequest.getSessionKeyB64(),registerRequest.getIvB64());
            WeixinPhoneDecryptInfo info = aes.decrypt();
            log.info("WeixinPhoneDecryptInfo:{}",info.toString());
            if(null == info){
                return CommonResult.failed("登录失败，请重新试！");
            }
            if(!WxConstants.WX_APPLET_APPID_ZXLP.equals(info.getWeixinWaterMark().getAppid())){
                return CommonResult.failed("APPID不正确，登录失败！");
            }
            registerRequest.setTelephone(info.getPhoneNumber());

        } catch (Exception e) {
            log.error("一键登录失败：{}",getExceptionToString(e));
            return CommonResult.failed("一键登录失败！");
        }
        return loginService.wxTokenLogin(registerRequest);
    }

    @PostMapping("bindNewPhone")
    public CommonResult bindNewPhone(@RequestBody RegisterRequest registerRequest) {
        UsersResponse currentUser = getCurrentUser();
        registerRequest.setUserId(currentUser.getId());
        registerRequest.setToken(currentUser.getToken());
        return loginService.bindNewPhone(registerRequest);
    }


    /**
     * 查询用户手机号是否存在
     *
     * @param registerRequest
     * @return
     */
    @PostMapping("/checkPhoneExist")
    public CommonResult checkPhoneExist(@RequestBody RegisterRequest registerRequest) {
        UsersResponse currentUser = getCurrentUser();
        registerRequest.setUserId(currentUser.getId());
        return loginService.checkPhoneExist(registerRequest);
    }

    /**
     * @Description 用户打标签
     *
     *
     *
     * @Version 1.0
     **/
    @PostMapping("/makeTag")
    public CommonResult makeTag(@RequestBody RegisterRequest registerRequest) {
        int userId = getCurrentUser().getId();
        registerRequest.setUserId(userId);
        loginService.makeTag(registerRequest);
        return CommonResult.success(ResultCode.SUCCESS);
    }


    /**
     * @Description 查询极光接口获取用户数据
     *
     *
     *
     * @Version 1.0
     **/
    @GetMapping("/recordUserData")
    public CommonResult recordUserData(@RequestParam(value = "imei", required = false) String imei) throws ParseException {

        return CommonResult.success(ResultCode.SUCCESS);
    }



    @Autowired
    private SysConfigUtil sysConfigUtil;

    /**
     * 环境 基础配置
     *
     * @return
     */
    @GetMapping("/environment")
    public CommonResult environment(@RequestParam("version") String version) {
        Map<String, Object> map = new HashMap<>();
        String environmentV = sysConfigUtil.getSysConfig(SysConfigConstants.ENVIRONMENT_V);
        if (version.equals(environmentV)) {
            String environment = sysConfigUtil.getSysConfig(SysConfigConstants.ENVIRONMENT);
            map.put("environment", environment);
        } else {
            map.put("environment", "PROD");
        }
        map.put("wxSwitch", sysConfigUtil.getSysConfig(SysConfigConstants.WX_SWITCH));
        map.put("distribution","顺丰配送");
        map.put("customerServiceUrl",sysConfigUtil.getSysConfig(SysConfigConstants.CUSTOMER_SERVICE));
        map.put("defaultScore",sysConfigUtil.getSysConfig(SysConfigConstants.DEFAULT_SCORE));
        map.put("officialUrl",sysConfigUtil.getSysConfig(SysConfigConstants.OFFICIAL_URL));
        map.put("PLATFORM_CHECK", sysConfigUtil.getSysConfig(SysConfigConstants.PLATFORM_CHECK));
        map.put("helpNum", RandomUtil.getSectionNum(1,10));
        return CommonResult.success(map);
    }

    /**
     * 保存APP 用户登录信息
     *
     */
    @PostMapping("/saveAppLogin")
    public CommonResult saveAppLogin (@RequestBody AppLoginRequest request) {
        loginService.saveAppLogin(request);
        return CommonResult.success();
    }

}
